'use strict';

const { Service } = require('ee-core');
const net = require('net');
const ModbusRTU = require("modbus-serial");
/**
 * 示例服务（service层为单例）
 * @class
 */
class ModbusServerTCPService extends Service {

  constructor(ctx) {
    super(ctx);
    // 存储活跃的Modbus客户端实例
    this.modbusClient = null;
  }

  async ServerTCP() { 

        // 配置参数
        const SERVER_PORT = 502; // Modbus TCP 默认端口
        const POLL_INTERVAL = 3000; // 轮询间隔(ms)
        const DEVICE_ADDRESS = 1; // 设备Modbus地址


        // 1. 创建TCP服务器等待设备连接
        const server = net.createServer((socket) => {
            console.log(`device connection: ${socket.remoteAddress}:${socket.remotePort}`);

            // 2. 创建Modbus客户端实例
            const client = new ModbusRTU();
            client.setSocket(socket, { keepAlive: true });
            
            // 存储当前连接
            this.modbusClient = client;

            // 监听连接关闭
            socket.on('close', () => {
                console.log('device disconnected');
                this.modbusClient = null;
            });

            // 监听错误
            socket.on('error', (err) => {
                console.error('connection error:', err.message);
                this.modbusClient = null;
            });
        });

        server.listen(SERVER_PORT, () => {
            console.log(`Modbus TCP starting，watch port: ${SERVER_PORT}`);
            console.log('waiting for client...');
        });

        server.on('connection', (socket) => { 
            console.log('client connected');
        });


        // 3. 定时轮询设备数据
        setInterval(() => {
            if (!this.modbusClient) {
                // console.log('waiting for device connection...');
                return;
            }

            // 示例：读取保持寄存器 (功能码03)
            const START_ADDRESS = 0; // 起始寄存器地址
            const LENGTH = 2;        // 读取寄存器数量

            this.modbusClient.readHoldingRegisters(START_ADDRESS, LENGTH)
                .then(data => {
                    console.log(`[${new Date().toLocaleTimeString()}] read success:`, data.data);
                })
                .catch(err => {
                    console.error('read fail:', err.message);
                    // 发生错误时重置连接
                    modbusClient = null;
                });
        }, POLL_INTERVAL);
    

  }

  async server(args) { 

    // create an empty modbus client

    const vector = {
        getInputRegister: function(addr, unitID) {
            // Synchronous handling
            return addr;
        },
        getHoldingRegister: function(addr, unitID, callback) {
            // Asynchronous handling (with callback)
            setTimeout(function() {
                // callback = function(err, value)
                callback(null, addr + 8000);
            }, 10);
        },
        getCoil: function(addr, unitID) {
            // Asynchronous handling (with Promises, async/await supported)
            return new Promise(function(resolve) {
                setTimeout(function() {
                    resolve((addr % 2) === 0);
                }, 10);
            });
        },
        setRegister: function(addr, value, unitID) {
            // Asynchronous handling supported also here
            console.log("set register", addr, value, unitID);
            return;
        },
        setCoil: function(addr, value, unitID) {
            // Asynchronous handling supported also here
            console.log("set coil", addr, value, unitID);
            return;
        },
        readDeviceIdentification: function(addr) {
            return {
                0x00: "MyVendorName",
                0x01: "MyProductCode",
                0x02: "MyMajorMinorRevision",
                0x05: "MyModelName",
                0x97: "MyExtendedObject1",
                0xAB: "MyExtendedObject2"
            };
        }
    };

    // set the server to answer for modbus requests
    let port = args.port || 8502;
    let unitID = args.id || 1;
    const serverTCP = new ModbusRTU.ServerTCP(vector, { host: "0.0.0.0", port, debug: true, unitID });
    console.log("ModbusTCP listening on modbus://0.0.0.0:" + port);

    serverTCP.on("socketError", function(err){
        // Handle socket error if needed, can be ignored
        console.error(err);
    });

  }
}

ModbusServerTCPService.toString = () => '[class ModbusServerTCPService]';
module.exports = ModbusServerTCPService;